package com.kinyx.framework.reflect.KBeanUtils_Tester;

import java.lang.reflect.Field;

import org.junit.Assert;
import org.junit.Test;

import com.kinyx.framework.reflect.KBeanUtils;
import com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1.PackageInnerBean;
import com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1.PackageStaticInnerBean;
import com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1.PackageStaticInnerBeanWithPackageNoArgConstructor;
import com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1.PackageStaticInnerBeanWithPrivateNoArgConstructor;
import com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1.PackageStaticInnerBeanWithProtectedNoArgConstructor;
import com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1.PackageStaticInnerBeanWithPublicNoArgConstructor;
import com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1.ProtectedInnerBean;
import com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1.ProtectedStaticInnerBeaWithPackageNoArgConstructorn;
import com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1.ProtectedStaticInnerBeaWithPrivateNoArgConstructorn;
import com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1.ProtectedStaticInnerBeaWithProtectedNoArgConstructorn;
import com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1.ProtectedStaticInnerBeaWithPublicNoArgConstructorn;
import com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1.ProtectedStaticInnerBean;
import com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1.PublicInnerBean;
import com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1.PublicStaticInnerBean;
import com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1.PublicStaticInnerBeanWithPackageNoArgConstructor;
import com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1.PublicStaticInnerBeanWithPrivateNoArgConstructor;
import com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1.PublicStaticInnerBeanWithProtectedNoArgConstructor;
import com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1.PublicStaticInnerBeanWithPublicNoArgConstructor;

public class _newInstance2 {

	private static void check(final boolean isNullStr, final Object instance, final Class<? extends Object> clazz) throws NoSuchFieldException, IllegalAccessException {
		final Field field = clazz.getDeclaredField("str");
		if (!field.isAccessible()) { field.setAccessible(true); }
		final Object str = field.get(instance);
		if (isNullStr) {
			Assert.assertNull(str);
		} else {
			Assert.assertEquals("str", str);
		}
	}

	private static void check(final Class<?> clazz, final boolean isNullStr) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
		final Object instance = KBeanUtils.newInstance(clazz);
		Assert.assertNotNull(instance);
		check(isNullStr, instance, clazz);
	}

	@Test
	public void test() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
		// 外部类正常反射调用
		check(PublicBean.class, true);
		check(PackageBean.class, true);
		// 内部类
		check(PublicInnerBean.class, true);
		check(ProtectedInnerBean.class, true);
		check(PackageInnerBean.class, true);
		//		check(PrivateInnerBean.class, true);
		// static 内部类
		check(PublicStaticInnerBean.class, true);
		check(ProtectedStaticInnerBean.class, true);
		check(PackageStaticInnerBean.class, true);
		//		check(PrivateStaticInnerBean.class, true);
		// static 内部类 with public NoArgConstructor
		check(PublicStaticInnerBeanWithPublicNoArgConstructor.class, false);
		check(ProtectedStaticInnerBeaWithPublicNoArgConstructorn.class, false);
		check(PackageStaticInnerBeanWithPublicNoArgConstructor.class, false);
		//		check(PrivateStaticInnerBeanWithPublicNoArgConstructor.class, false);
		// static 内部类 with protected NoArgConstructor
		check(PublicStaticInnerBeanWithProtectedNoArgConstructor.class, false);
		check(ProtectedStaticInnerBeaWithProtectedNoArgConstructorn.class, false);
		check(PackageStaticInnerBeanWithProtectedNoArgConstructor.class, false);
		//		check(PrivateStaticInnerBeanWithProtectedNoArgConstructor.class, false);
		// static 内部类 with package NoArgConstructor
		check(PublicStaticInnerBeanWithPackageNoArgConstructor.class, false);
		check(ProtectedStaticInnerBeaWithPackageNoArgConstructorn.class, false);
		check(PackageStaticInnerBeanWithPackageNoArgConstructor.class, false);
		//		check(PrivateStaticInnerBeanWithPackageNoArgConstructor.class, false);
		// static 内部类 with private NoArgConstructor
		check(PublicStaticInnerBeanWithPrivateNoArgConstructor.class, false);
		check(ProtectedStaticInnerBeaWithPrivateNoArgConstructorn.class, false);
		check(PackageStaticInnerBeanWithPrivateNoArgConstructor.class, false);
		//		check(PrivateStaticInnerBeanWithPrivateNoArgConstructor.class, false);
	}

	private static void check(final String className, final boolean isNullStr) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
		final Object instance = KBeanUtils.newInstance(className);
		Assert.assertNotNull(instance);
		final Class<? extends Object> clazz = instance.getClass();
		check(isNullStr, instance, clazz);
	}

	@Test
	public void test2() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
		// 外部类正常反射调用
		check("com.kinyx.framework.reflect.KBeanUtils_Tester.PublicBean", true);
		check("com.kinyx.framework.reflect.KBeanUtils_Tester.PackageBean", true);
		// 内部类
		check("com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1$PublicInnerBean", true);
		check("com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1$ProtectedInnerBean", true);
		check("com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1$PackageInnerBean", true);
		check("com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1$PrivateInnerBean", true);
		// static 内部类
		check("com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1$PublicStaticInnerBean", true);
		check("com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1$ProtectedStaticInnerBean", true);
		check("com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1$PackageStaticInnerBean", true);
		check("com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1$PrivateStaticInnerBean", true);
		// static 内部类 with public NoArgConstructor
		check("com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1$PublicStaticInnerBeanWithPublicNoArgConstructor", false);
		check("com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1$ProtectedStaticInnerBeaWithPublicNoArgConstructorn", false);
		check("com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1$PackageStaticInnerBeanWithPublicNoArgConstructor", false);
		check("com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1$PrivateStaticInnerBeanWithPublicNoArgConstructor", false);
		// static 内部类 with protected NoArgConstructor
		check("com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1$PublicStaticInnerBeanWithProtectedNoArgConstructor", false);
		check("com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1$ProtectedStaticInnerBeaWithProtectedNoArgConstructorn", false);
		check("com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1$PackageStaticInnerBeanWithProtectedNoArgConstructor", false);
		check("com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1$PrivateStaticInnerBeanWithProtectedNoArgConstructor", false);
		// static 内部类 with package NoArgConstructor
		check("com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1$PublicStaticInnerBeanWithPackageNoArgConstructor", false);
		check("com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1$ProtectedStaticInnerBeaWithPackageNoArgConstructorn", false);
		check("com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1$PackageStaticInnerBeanWithPackageNoArgConstructor", false);
		check("com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1$PrivateStaticInnerBeanWithPackageNoArgConstructor", false);
		// static 内部类 with private NoArgConstructor
		check("com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1$PublicStaticInnerBeanWithPrivateNoArgConstructor", false);
		check("com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1$ProtectedStaticInnerBeaWithPrivateNoArgConstructorn", false);
		check("com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1$PackageStaticInnerBeanWithPrivateNoArgConstructor", false);
		check("com.kinyx.framework.reflect.KBeanUtils_Tester._newInstance1$PrivateStaticInnerBeanWithPrivateNoArgConstructor", false);
	}

}
